home *** CD-ROM | disk | FTP | other *** search
- /***********************************************************
- Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
- The Netherlands.
-
- All Rights Reserved
-
- Permission to use, copy, modify, and distribute this software and its
- documentation for any purpose and without fee is hereby granted,
- provided that the above copyright notice appear in all copies and that
- both that copyright notice and this permission notice appear in
- supporting documentation, and that the names of Stichting Mathematisch
- Centrum or CWI or Corporation for National Research Initiatives or
- CNRI not be used in advertising or publicity pertaining to
- distribution of the software without specific, written prior
- permission.
-
- While CWI is the initial source for this software, a modified version
- is made available by the Corporation for National Research Initiatives
- (CNRI) at the Internet address ftp://ftp.python.org.
-
- STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
- REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
- CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
- DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
- PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- PERFORMANCE OF THIS SOFTWARE.
-
- ******************************************************************/
-
- /* Module support implementation */
-
- #include "allobjects.h"
- #include "import.h"
-
- #ifdef MPW /* MPW pushes 'extended' for float and double types with varargs */
- typedef extended va_double;
- #else
- typedef double va_double;
- #endif
-
- /* initmodule4() parameters:
- - name is the module name
- - methods is the list of top-level functions
- - doc is the documentation string
- - passthrough is passed as self to functions defined in the module
- - api_version is the value of PYTHON_API_VERSION at the time the
- module was compiled
- */
-
- static char api_version_warning[] =
- "WARNING: Python C API version mismatch for module %s:\n\
- This Python has API version %d, module %s has version %d.\n";
-
- object *
- initmodule4(name, methods, doc, passthrough, module_api_version)
- char *name;
- struct methodlist *methods;
- char *doc;
- object *passthrough;
- int module_api_version;
- {
- object *m, *d, *v;
- struct methodlist *ml;
- if (module_api_version != PYTHON_API_VERSION)
- fprintf(stderr, api_version_warning,
- name, PYTHON_API_VERSION, name, module_api_version);
- if ((m = add_module(name)) == NULL) {
- fprintf(stderr, "initializing module: %s\n", name);
- fatal("can't create a module");
- }
- d = getmoduledict(m);
- for (ml = methods; ml->ml_name != NULL; ml++) {
- v = newmethodobject(ml, passthrough);
- if (v == NULL || dictinsert(d, ml->ml_name, v) != 0) {
- fprintf(stderr, "initializing module: %s\n", name);
- fatal("can't initialize module");
- }
- DECREF(v);
- }
- if (doc != NULL) {
- v = newstringobject(doc);
- if (v == NULL || dictinsert(d, "__doc__", v) != 0)
- fatal("can't add doc string");
- DECREF(v);
- }
- return m;
- }
-
-
- /* Helper for mkvalue() to scan the length of a format */
-
- static int countformat PROTO((char *format, int endchar));
- static int countformat(format, endchar)
- char *format;
- int endchar;
- {
- int count = 0;
- int level = 0;
- while (level > 0 || *format != endchar) {
- switch (*format) {
- case '\0':
- /* Premature end */
- err_setstr(SystemError, "unmatched paren in format");
- return -1;
- case '(':
- case '[':
- case '{':
- if (level == 0)
- count++;
- level++;
- break;
- case ')':
- case ']':
- case '}':
- level--;
- break;
- case '#':
- case '&':
- case ',':
- case ':':
- case ' ':
- case '\t':
- break;
- default:
- if (level == 0)
- count++;
- }
- format++;
- }
- return count;
- }
-
-
- /* Generic function to create a value -- the inverse of getargs() */
- /* After an original idea and first implementation by Steven Miale */
-
- static object *do_mktuple PROTO((char**, va_list *, int, int));
- static object *do_mklist PROTO((char**, va_list *, int, int));
- static object *do_mkdict PROTO((char**, va_list *, int, int));
- static object *do_mkvalue PROTO((char**, va_list *));
-
-
- static object *
- do_mkdict(p_format, p_va, endchar, n)
- char **p_format;
- va_list *p_va;
- int endchar;
- int n;
- {
- object *d;
- int i;
- if (n < 0)
- return NULL;
- if ((d = newdictobject()) == NULL)
- return NULL;
- for (i = 0; i < n; i+= 2) {
- object *k, *v;
- k = do_mkvalue(p_format, p_va);
- if (k == NULL) {
- DECREF(d);
- return NULL;
- }
- v = do_mkvalue(p_format, p_va);
- if (v == NULL) {
- DECREF(k);
- DECREF(d);
- return NULL;
- }
- if (dict2insert(d, k, v) < 0) {
- DECREF(k);
- DECREF(v);
- DECREF(d);
- return NULL;
- }
- }
- if (d != NULL && **p_format != endchar) {
- DECREF(d);
- d = NULL;
- err_setstr(SystemError, "Unmatched paren in format");
- }
- else if (endchar)
- ++*p_format;
- return d;
- }
-
- static object *
- do_mklist(p_format, p_va, endchar, n)
- char **p_format;
- va_list *p_va;
- int endchar;
- int n;
- {
- object *v;
- int i;
- if (n < 0)
- return NULL;
- if ((v = newlistobject(n)) == NULL)
- return NULL;
- for (i = 0; i < n; i++) {
- object *w = do_mkvalue(p_format, p_va);
- if (w == NULL) {
- DECREF(v);
- return NULL;
- }
- setlistitem(v, i, w);
- }
- if (v != NULL && **p_format != endchar) {
- DECREF(v);
- v = NULL;
- err_setstr(SystemError, "Unmatched paren in format");
- }
- else if (endchar)
- ++*p_format;
- return v;
- }
-
- static object *
- do_mktuple(p_format, p_va, endchar, n)
- char **p_format;
- va_list *p_va;
- int endchar;
- int n;
- {
- object *v;
- int i;
- if (n < 0)
- return NULL;
- if ((v = newtupleobject(n)) == NULL)
- return NULL;
- for (i = 0; i < n; i++) {
- object *w = do_mkvalue(p_format, p_va);
- if (w == NULL) {
- DECREF(v);
- return NULL;
- }
- settupleitem(v, i, w);
- }
- if (v != NULL && **p_format != endchar) {
- DECREF(v);
- v = NULL;
- err_setstr(SystemError, "Unmatched paren in format");
- }
- else if (endchar)
- ++*p_format;
- return v;
- }
-
- static object *
- do_mkvalue(p_format, p_va)
- char **p_format;
- va_list *p_va;
- {
- for (;;) {
- switch (*(*p_format)++) {
- case '(':
- return do_mktuple(p_format, p_va, ')',
- countformat(*p_format, ')'));
-
- case '[':
- return do_mklist(p_format, p_va, ']',
- countformat(*p_format, ']'));
-
- case '{':
- return do_mkdict(p_format, p_va, '}',
- countformat(*p_format, '}'));
-
- case 'b':
- case 'h':
- case 'i':
- return newintobject((long)va_arg(*p_va, int));
-
- case 'l':
- return newintobject((long)va_arg(*p_va, long));
-
- case 'f':
- case 'd':
- return newfloatobject((double)va_arg(*p_va, va_double));
-
- case 'c':
- {
- char p[1];
- p[0] = va_arg(*p_va, int);
- return newsizedstringobject(p, 1);
- }
-
- case 's':
- case 'z':
- {
- object *v;
- char *str = va_arg(*p_va, char *);
- int n;
- if (**p_format == '#') {
- ++*p_format;
- n = va_arg(*p_va, int);
- }
- else
- n = -1;
- if (str == NULL) {
- v = None;
- INCREF(v);
- }
- else {
- if (n < 0)
- n = strlen(str);
- v = newsizedstringobject(str, n);
- }
- return v;
- }
-
- case 'S':
- case 'O':
- if (**p_format == '&') {
- typedef object *(*converter) PROTO((void *));
- converter func = va_arg(*p_va, converter);
- void *arg = va_arg(*p_va, void *);
- ++*p_format;
- return (*func)(arg);
- }
- else {
- object *v;
- v = va_arg(*p_va, object *);
- if (v != NULL)
- INCREF(v);
- else if (!err_occurred())
- /* If a NULL was passed
- * because a call that should
- * have constructed a value
- * failed, that's OK, and we
- * pass the error on; but if
- * no error occurred it's not
- * clear that the caller knew
- * what she was doing. */
- err_setstr(SystemError,
- "NULL object passed to mkvalue");
- return v;
- }
-
- case ':':
- case ',':
- case ' ':
- case '\t':
- break;
-
- default:
- err_setstr(SystemError,
- "bad format char passed to mkvalue");
- return NULL;
-
- }
- }
- }
-
-
- #ifdef HAVE_STDARG_PROTOTYPES
- /* VARARGS 2 */
- object *mkvalue(char *format, ...)
- #else
- /* VARARGS */
- object *mkvalue(va_alist) va_dcl
- #endif
- {
- va_list va;
- object* retval;
- #ifdef HAVE_STDARG_PROTOTYPES
- va_start(va, format);
- #else
- char *format;
- va_start(va);
- format = va_arg(va, char *);
- #endif
- retval = vmkvalue(format, va);
- va_end(va);
- return retval;
- }
-
- object *
- vmkvalue(format, va)
- char *format;
- va_list va;
- {
- char *f = format;
- int n = countformat(f, '\0');
- va_list lva;
-
- #ifdef VA_LIST_IS_ARRAY
- memcpy(lva, va, sizeof(va_list));
- #else
- lva = va;
- #endif
-
- if (n < 0)
- return NULL;
- if (n == 0) {
- INCREF(None);
- return None;
- }
- if (n == 1)
- return do_mkvalue(&f, &lva);
- return do_mktuple(&f, &lva, '\0', n);
- }
-
-
- #ifdef HAVE_STDARG_PROTOTYPES
- object *
- PyEval_CallFunction(object *obj, char *format, ...)
- #else
- object *
- PyEval_CallFunction(obj, format, va_alist)
- object *obj;
- char *format;
- va_dcl
- #endif
- {
- va_list vargs;
- object *args;
- object *res;
-
- #ifdef HAVE_STDARG_PROTOTYPES
- va_start(vargs, format);
- #else
- va_start(vargs);
- #endif
-
- args = vmkvalue(format, vargs);
- va_end(vargs);
-
- if (args == NULL)
- return NULL;
-
- res = call_object(obj, args);
- DECREF(args);
-
- return res;
- }
-
-
- #ifdef HAVE_STDARG_PROTOTYPES
- object *
- PyEval_CallMethod(object *obj, char *methonname, char *format, ...)
- #else
- object *
- PyEval_CallMethod(obj, methonname, format, va_alist)
- object *obj;
- char *methonname;
- char *format;
- va_dcl
- #endif
- {
- va_list vargs;
- object *meth;
- object *args;
- object *res;
-
- meth = getattr(obj, methonname);
- if (meth == NULL)
- return NULL;
-
- #ifdef HAVE_STDARG_PROTOTYPES
- va_start(vargs, format);
- #else
- va_start(vargs);
- #endif
-
- args = vmkvalue(format, vargs);
- va_end(vargs);
-
- if (args == NULL) {
- DECREF(meth);
- return NULL;
- }
-
- res = call_object(meth, args);
- DECREF(meth);
- DECREF(args);
-
- return res;
- }
-